


#include "door.h"
#include "mutator.h"



// DoorMutator ::



DoorMutator::DoorMutator( CollectionSubjects *subs, CollectionCategories *cats )
    : Mutator(subs, cats)
    , m_bSignsMutated( false )
{
}



/// \return true if full mutation done
bool DoorMutator::mutate()
{
    while(true)
    {
        if( Mutator::mutate() )
        {
            if( !m_bSignsMutated )
            {
                // find the 2 subjects with lost signs
                Subject *subject1 = NULL, *subject2 = NULL;   
                CollectionSubjects::iterator is = m_pSubjects->begin(), is_end = m_pSubjects->end();
                for( ; is != is_end; ++is )
                {
                    Door *door = static_cast <Door*> (*is);
                    if( !door->hasSign() )
                    {
                        if( subject1 )
                        {
                            subject2 = door;
                            break;
                        }
                        else
                        {
                            subject1 = door;   
                        }
                    }
                } // for( ; is != is_end; ++is )
                
                // swap the collections of the found subjs
                if( subject1 && subject2 )
                {
                    CollectionExpressions *tmpexprs = &subject1->getExpressions();
                    subject1->mutateExpressions( &subject2->getExpressions() );
                    subject2->mutateExpressions( tmpexprs );
                    m_bSignsMutated = true;
                    return false;
                }
            } 
            else // if( !m_bSignsMutated )
            {
                m_bSignsMutated = false;
            }

            return true;
        }
        else // if( Mutator::mutate() )
        {
            // check if all doors have mutated to traps
            CollectionSubjects::iterator id = m_pSubjects->begin(), id_end = m_pSubjects->end();
            for( ; id != id_end; ++id )
            {
                Door *door = static_cast <Door*> (*id);
                if( door->isSafe() )
                    return false;
            }
            // otherwise all doors have mutated to traps - continue the loop and mutate again
        }
    } // while(true)
}

